package com.mgq.juc.c1;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;

/**
 * @author MaGuangQi
 * 测试偏向锁的对象头
 * @date 2021-12-15 11:22
 **/
@Slf4j
public class TestBiasedLock {
    public static void main(String[] args) {
       // testHashCode();
        //testBiasedLock();
        //testCloseBiasedLock();
        testThreadBiasedLock();
    }

    private static void testHashCode() {
        Dog dog = new Dog();
        //hashCode()方法会直接让偏向锁失效. 原因是hashCode把偏向锁的线程id占用了,导致无法使用偏向锁了
        dog.hashCode();
        log.debug(ClassLayout.parseInstance(dog).toPrintable());
    }
    private static void testBiasedLock() {
        // 正常创建的对象,默认就是偏向锁
        //注意:默认刚启动不开启偏向锁,如果要立即产生 使用 -XX:BiasedLockingStartupDelay=0 禁用延迟
        Dog dog = new Dog();
        log.debug(ClassLayout.parseInstance(dog).toPrintable());
    }
    private static void testCloseBiasedLock() {
       // -XX:-UseBiasedLocking 关闭偏向锁,此时会使用轻量级锁
        Dog dog = new Dog();
        log.debug(ClassLayout.parseInstance(dog).toPrintable());
    }
    private static void testThreadBiasedLock() {
        // 当有第2个线程尝试使用偏向锁时,会导致偏向锁失效
        Dog dog = new Dog();
        new Thread(()->{
            log.debug("加锁前:"+ClassLayout.parseInstance(dog).toPrintable());
            synchronized (dog) {
                log.debug("加锁:"+ClassLayout.parseInstance(dog).toPrintable());
            }
            log.debug("释放锁:"+ClassLayout.parseInstance(dog).toPrintable());
            synchronized (TestBiasedLock.class) {
                TestBiasedLock.class.notifyAll();
            }
        },"t1").start();
        //使用wait/notifyAll() 是为了让线程1先使用偏向锁,使用完之后线程2再使用
        //如果直接竞争,就直接变为重量级锁了
        new Thread(()->{
            synchronized (TestBiasedLock.class) {
                try {
                    TestBiasedLock.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            log.debug("加锁前:"+ClassLayout.parseInstance(dog).toPrintable());
            synchronized (dog) {
                log.debug("加锁:"+ClassLayout.parseInstance(dog).toPrintable());
            }
            log.debug("释放锁:"+ClassLayout.parseInstance(dog).toPrintable());

        },"t2").start();
    }
}

class Dog {

}
